﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aletfa.LightManager.Effects;
using System.ComponentModel;

namespace Aletfa.LightManager
{
    internal sealed class GameManager
    {
        public int CurrentTurn { get; private set; }

        public BindingList<Action> Actions { get; set; }

        public BindingList<Unit> Units { get; set; }

        public bool InBattle { get; private set; }

        public event GenericEventHandler<Unit> UnitChanged;
        public event GenericEventHandler<string> LogNeeded;
        public event GenericEventHandler<bool> BoardSetup;
        public event UnitArgumentEventHandler UnitLifeChanged;

        private List<Guid> ActiveEffects { get; set; }

        //private MusicPlayer Music = new MusicPlayer();

        public GameManager()
        {
            this.Actions = new BindingList<Action>();
            this.Units = new BindingList<Unit>();
            this.ActiveEffects = new List<Guid>();
            this.CurrentTurn = 0;
            this.InBattle = false;
        }

        public void RegisterAction(Action action)
        {
            if (action.Countdown == 0)
                this.PerformAction(action);
            
            if (action.Duration > action.InProgress)
                this.Actions.Add(action);
        }

        public void NextTurn()
        {
            this.RequestBoardSetup(false);
            this.InBattle = true;
            this.CurrentTurn++;
            this.LogNeeded(string.Format("<font class='battle'>{0}° turno</font>", this.CurrentTurn));
            for (int i = this.Actions.Count - 1; i >= 0; i--)
            {
                Action action = this.Actions[i];
                if (action.Countdown > 0)
                {
                    action.Countdown--;
                    continue;
                }
                this.PerformAction(action);
            }
            //this.Music.Battle();
        }

        public void EndFight()
        {
            this.LogNeeded("<font class='battle'>Battaglia completata!</font>");
            //this.Music.Victory();

            for (int i = this.Units.Count - 1; i >= 0; i--)
            {
                if (this.Units[i].IsEnemy)
                    this.Units.RemoveAt(i);
                else
                {
                    this.Units[i].Reset();
                    this.UnitChanged(this.Units[i]);
                }
            }
            for (int i = this.Actions.Count - 1; i >= 0; i--)
                if (this.Actions[i].IsTemporary)
                    this.PerformUndo(this.Actions[i]);
            this.Actions.Clear();
            this.ActiveEffects.Clear();

            this.CurrentTurn = 0;
            this.InBattle = false;
        }

        public void NotifyUnitChanged(Unit unit)
        {
            if (this.UnitChanged != null)
                this.UnitChanged(unit);
        }

        public void RemoveUnit(Unit unit)
        {
            for (int i = this.Actions.Count - 1; i >= 0; i--)
                if (this.Actions[i].Target.Id == unit.Id)
                {
                    this.ActiveEffects.Remove(this.Actions[i].Id);
                    this.Actions.RemoveAt(i);
                }

            this.Units.Remove(unit);
        }

        public void RemoveAction(Action action)
        {
            if (action.IsTemporary)
                this.PerformUndo(action);
            this.Actions.Remove(action);
            this.ActiveEffects.Remove(action.Id);
        }

        private void PerformAction(Action action)
        {
            if (!this.ActiveEffects.Contains(action.Id))
            {
                int life = action.Target.LifeCount;
                string result = action.Perform();
                if (life != action.Target.LifeCount)
                    if (this.UnitLifeChanged != null)
                        this.UnitLifeChanged(action.Target, action.Target.LifeCount - life);
                if (this.LogNeeded != null)
                    this.LogNeeded(result);
                this.NotifyUnitChanged(action.Target);
                if (action.IsOneShot)
                    this.ActiveEffects.Add(action.Id);
            }

            action.InProgress++;

            if (action.InProgress >= action.Duration)
                this.RemoveAction(action);
        }

        private void PerformUndo(Action action)
        {
            string result = action.Undo();
            if (this.LogNeeded != null)
                this.LogNeeded(result);
            this.NotifyUnitChanged(action.Target);
        }

        internal void RequestBoardSetup(bool enable)
        {
            this.BoardSetup(enable);
        }
    }
}
